#include<iostream>
#include<unistd.h>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<string>
#include<sys/types.h>
#include<sys/wait.h>
using namespace std;

const int basesize = 1024;
const int argvnum = 64;
const int envnum = 64;

//全局命令行列表参数
char* gargv[argvnum];
int gargc = 0;
//我的系统环境变量
char* genv[envnum];
//全局shell当前工作路径
char pwd[basesize];
char pwdenv[basesize];
string  Getuesename()
{
    string name = getenv("USER");
    return name;
}
string Gethostname()
{
    string hosename = getenv("HOSTNAME");
    return hosename;
}
string Getpwd()
{
    if(nullptr == getcwd(pwd,sizeof(pwd))) return "None";
    snprintf(pwdenv,sizeof(pwdenv),"PWD=%s",pwd);
    putenv(pwdenv);

    return pwd;
}
string makeuserline()
{
    char commit_line[basesize];
    snprintf(commit_line , basesize , "[%s@%s %s]# ",\
            Getuesename().c_str(),Gethostname().c_str(),Getpwd().c_str());
    return commit_line;
}
void printcommitline()
{
    printf("%s",makeuserline().c_str());
    fflush(stdout);
}
bool getcommitline(char commit_buffer[] ,int size)
{
    char* result = fgets(commit_buffer,size,stdin);
    if(!result)
    {
        return false;
    }
    commit_buffer[strlen(commit_buffer)-1] = 0;
    if(strlen(commit_buffer) == 0) return false;
    return true;
}
void parseCommitline(char commit_buffer[],int size)
{
    (void)size;
    memset(gargv,0,sizeof(gargv));
    gargc = 0;
    const char* seq = " ";
    gargv[gargc++] = strtok(commit_buffer,seq);
   while((bool)(gargv[gargc++] = strtok(nullptr,seq)));
    gargc--;
}
void debug()
{
    printf("gargc= %d\n",gargc);
    for(int i = 0;gargv[i];i++)
    {
        printf("argv[%d]: %s\n",i,gargv[i]);
    }
}
bool Executecommit()
{
    pid_t id = fork();
    if(id <  0) return false;
    if(id == 0)
    {
        //子进程
        //1，执行命令
        execvp(gargv[0],gargv);
        //2，退出
        exit(1);
    }
    int status = 0;
    pid_t rid = waitpid(id,&status,0);
    if(rid > 0)
    {
        //
        if(WIFEXITED(status))
        {

        }
        
        return true;
    }
    return false;
}
void AddEnv(const char* item)
{
    int index = 0;
    while(genv[index])
    {
        index++;
    }
    genv[index++] = (char*)malloc(strlen(item)+1);
    strncpy(genv[index],item,strlen(item)+1);
    genv[++index] = nullptr;
}
bool CheakAndExeBuiltCommand()
{
    if(strcmp(gargv[0],"cd") == 0)
    {
        if(gargc == 2)
        {
            chdir(gargv[1]);
        }
        return true;
    }
    else if(strcmp(gargv[0],"export") == 0)
    {
        if(gargc == 2)
        {
            AddEnv(gargv[1]);
        }
        return true;
    }
    else if(strcmp(gargv[0],"env") == 0)
    {
        for(int i = 0;genv[i];i++)
        {
            printf("%s\n",genv[i]);
        }
        return true;
    }
    return false;
}
void InitEnv()
{
    extern char ** environ;
    int index = 0;
    while(environ[index])
    {
        genv[index] = (char*)malloc(strlen(environ[index]+1));
        strncpy(genv[index],environ[index],strlen(environ[index]+1));
        index++;
    }
    genv[index] = nullptr;
}
int main()
{
    InitEnv();
    char commit_buffer[basesize];
    while(1)
    {
        //打印用户登录界面
        printcommitline();
        if(!getcommitline(commit_buffer,basesize))
        {
            continue;
        }
        //printf("%s",commit_buffer);
        //sleep(1);
        parseCommitline(commit_buffer,strlen(commit_buffer));
        if(CheakAndExeBuiltCommand())
        {
            continue;
        }
       //debug(); 
       Executecommit();
    }
    return 0;
}
